from pkgr.package import InstalledPackage, Requires, Provides
import rpm
import logging
logger = logging.getLogger('pkgr.rpm')

class RPMInstalledPackage(InstalledPackage):
    def __init__(self, h):
        self.header = h
        super(RPMInstalledPackage, self).__init__(None, name=h['name'], version=h['version'], epoch=h['epoch'], release=h['release'], arch=h['arch'])
    
    def get_requires(self):
        for prov in self.header[rpm.RPMTAG_REQUIRES]:
            yield Requires(prov)
        
    @classmethod 
    def from_file(cls, db, f):
        return cls(db.load_header_from_package(f))
    
    def stringToVersion(self,verstring):
        if verstring in [None, '']:
            return (None, None, None)
        i = verstring.find(':')
        if i != -1:
            try:
                epoch = str(long(verstring[:i]))
            except ValueError:
                # look, garbage in the epoch field, how fun, kill it
                epoch = '0' # this is our fallback, deal
        else:
            epoch = '0'
        j = verstring.find('-')
        if j != -1:
            if verstring[i + 1:j] == '':
                version = None
            else:
                version = verstring[i + 1:j]
            release = verstring[j + 1:]
        else:
            if verstring[i + 1:] == '':
                version = None
            else:
                version = verstring[i + 1:]
            release = None
        return (epoch, version, release)
        
    def flagToString(self, flags):
        flags = flags & 0xf
    
        if flags == 0: return None
        elif flags == 2: return 'LT'
        elif flags == 4: return 'GT'
        elif flags == 8: return 'EQ'
        elif flags == 10: return 'LE'
        elif flags == 12: return 'GE'
    
        return flags
    
    def _flag_to_string(self):
         # Flag must be set and a int (or a long, now)
        if not flags:
            return None
            
        if not isinstance(flags, (long, int)):
            return None
        
        operator = None
        
        if flags & (rpm.RPMSENSE_LESS | rpm.RPMSENSE_EQUAL):
            operator = "<="
        elif flags & (rpm.RPMSENSE_GREATER | rpm.RPMSENSE_EQUAL):
            operator = "<="
        elif flags & rpm.RPMSENSE_LESS:
            operator =  "<"
        elif flags & rpm.RPMSENSE_GREATER:
            operator =  ">"
        elif flags & rpm.RPMSENSE_EQUAL:
            operator = "="
        else:
            raise Exception('Unknown flag value %s' % flags)
        return operator
            
    def _format_require(self, name, version, flags):
        '''
        Return a human readable requirement string (ex.  foobar >= 2.0)
        @param name: requirement name (ex. foobar)
        @param version: requirent version (ex. 2.0)
        @param flags: binary flags ( 0010 = equal, 0100 = greater than, 1000 = less than )
        '''
        string = [name]
        
        operator = self.flagToString(flags)
        
        if operator:
            string.append(operator)
            
        if not version:
            return (name, None, None, None, None)
            
        e,v,r = self.stringToVersion(version)
        return (name, operator, v, r, e)
        return name, e, v, r
    
    def get_requires(self):
        arch = self.header[rpm.RPMTAG_ARCH]
        
        for n,f,v in zip(self.header[rpm.RPMTAG_REQUIRENAME], self.header[rpm.RPMTAG_REQUIREFLAGS], self.header[rpm.RPMTAG_REQUIREVERSION]):
            name, operator, v, r, e= self._format_require(n,v,f)
            yield Requires(name.strip(), operator, v, r, e, arch)
            
    def get_provides(self, filenames=True):
        arch = self.header[rpm.RPMTAG_ARCH]
        yield Provides(self.get_name())
        yield Provides(self.get_name(), arch=arch)
        e, v, r = self.get_evr()
        yield Provides(self.get_name(), "EQ", v, r, e, arch=arch)
            
        for n,f,v in zip(self.header[rpm.RPMTAG_PROVIDENAME], self.header[rpm.RPMTAG_PROVIDEFLAGS], self.header[rpm.RPMTAG_PROVIDEVERSION]):
            name, operator, v, r, e= self._format_require(n,v,f)
            yield Provides(name.strip(), operator, v, r, e, arch)
        
        if filenames:
            for n in self.header[rpm.RPMTAG_FILENAMES]:
                yield Provides(n.strip())
            
        
    def requires(self, r):
        logger.debug('Checking if %s requires %s: %s', self, r, list(self.get_requires()))
        for prov in self.get_requires():
            if r == prov:
                return True
        return False
        
    def get_all_provides(self):
        
        #nv=zip(hdr[rpm.RPMTAG_PROVIDENAME],hdr[rpm.RPMTAG_PROVIDEVERSION])
        
        for prov in self.header[rpm.RPMTAG_PROVIDENAME]:
            yield prov
            
        for prov in self.header[rpm.RPMTAG_PROVIDES]:
            yield prov
            
        for prov in self.header[rpm.RPMTAG_FILENAMES]:
            yield prov
        for prov in self.header[rpm.RPMTAG_PROVIDENAME]:
            yield prov                                                                       
           
    def __repr__(self):
        return "<InstalledPackage(%s-%s-%s:%s, %s)>" % (
            self.get_name(),
            self.get_version(), 
            self.get_release(), 
            self.get_epoch(),
            self.get_arch()
        )
      
  
'''
def printHeader(h):
    if h[rpm.RPMTAG_SOURCEPACKAGE]:
        extra = " source package"
    else:
        extra = " binary package"
    printEntry(h, 'Package', "%{NAME}-%{VERSION}-%{RELEASE}", extra)
    printEntry(h, 'Group', "%{GROUP}", '')
    printEntry(h, 'Summary', "%{Summary}", '')
    printEntry(h, 'Arch-OS-Platform', "%{ARCH}-%{OS}-%{PLATFORM}", '')
    printEntry(h, 'Vendor', "%{Vendor}", '')
    printEntry(h, 'URL', "%{URL}", '')
    printEntry(h, 'Size', "%{Size}", '')
    printEntry(h, 'Installed on', "%{INSTALLTID:date}", '')
    print h['description']
    print "Files:"
    fi = h.fiFromHeader()
    print fi

    # Dependencies
    print "Provides:"
    print h.dsFromHeader('providename')

    print "Requires:"
    print h.dsFromHeader('requirename')

    if h.dsFromHeader('obsoletename'):
        print "Obsoletes:"
        print h.dsFromHeader('obsoletename')

    if h.dsFromHeader('conflictname'):
        print "Conflicts:"
        print h.dsFromHeader('conflictname')

class RPMHeader(object):
    def __init__(self, h):
        self.header = h
        tup = miscutils.pkgTupleFromHeader(h)
        for prov in hdr[rpm.RPMTAG_PROVIDES]:
            yield prov
            
        for prov in hdr[rpm.RPMTAG_FILENAMES]:
            yield prov
        
        for r in h[rpm.RPMTAG_REQUIRENAME]:
            pass
'''
